;-----------------------------------------------------------------------------
;
;	Overlay for ZMP ffor HP12X                     
;
;	Name	zmo-hp.azm   
;
;	set up for compile with z80mr
;
;	Written by -
;	  Ron Murray, c/o Z-Node 62, 061-9-450-0200, Perth, Western Australia.
;
; 89/04/12 - Modified to ZMP v1.5		- George Conover
;	Modified to ZMP v1.2 standard rjm 15/9/88
;	Modified to ZMP v1.3 standard rjm 11/10/88
;	Modified to ZMP v1.4 standard rjm 20/11/88
;       Added HP code MWR 2/8/89
;       Attemp at correct cursor contrl 2/10/89
;
;-----------------------------------------------------------------------------
;
;
;	System-dependent code overlay for ZMODEM
;
;
;
;    Insert your own code as necessary in this file. Code contained herein
; has been written in Z80 code for use with M80 or SLR. Assemble as follows:
;
;	SLR ZMO-xx01/h
;	MLOAD ZMP.COM=ZMODEM.COM,ZMO-xx01.HEX
; or
;	M80 =ZMO-xx01.Z80
;	RELHEX ZMO-xx01
;	MLOAD ZMP.COM=ZMODEM.COM,ZMO-xx01.HEX
;
;
;       (Don't use L80 without changing the source for assembly as a
;         cseg file.)
;
;-----------------------------------------------------------------------------
;
;
; Notes on modifying this file:
;
;    C requires that functions do not change either index register (IX or IY).
; If your overlay requires either of these to be changed, ensure they are
; restored to the original values on return.
;    Since collecting parameters from C functions can be tricky, only change
; the parts marked 'Insert your own code here'. Do NOT modify the jump
; table at the start. Do NOT modify the entry/exit sections of each
; function. Do NOT pass 'GO'. Do NOT collect $200.
;    Apart from defining modem functions, this file also defines terminal
; characteristics. Examples provided are for ADM-3A (with a few of my own
; additions). Modify to suit your own terminal. An inline print routine
; is provided for printing strings in the usual way: usage is
;
;	call	print
;	db	'required string',0
;
;-----------------------------------------------------------------------------
;
;
;    Don't forget to set your clock speed at the clkspd variable.
;
;
;    If you find your overlay exceeds the maximum size (currently 0400h),
; you will have to contact me for another version. If too many people need 
; to do it, we haven't allowed enough room.
;
; Ron Murray 15/8/88
;
;
;
;---------------------------------------------------------------------------

false	equ	0
true	equ	1        

;------------------------------------------------------------------------------

; User-set variables: 

clkspd	equ	4		; Processor clock speed in MHz
debug	equ	false		; to allow debugging of overlay with Z8E etc.

;Set the following two equates to the drive and user area which will contain
;   ZMP's .OVR files, .CFG file, .FON file and .HLP file. Set both to zero
;   (null) to locate them on the drive from which ZMP was invoked.

overdrive	equ	'B'	; Drive to find overlay files on ('A'-'P')
overuser	equ	0	; User area to find files

;------------------------------------------------------------------------------


; NOT user-set variables

userdef	equ	0145h		; origin of this overlay
				; This address should not change with
				; subsequent revisions.
mspeed	equ	03ch		; location of current baud rate. 
ovsize	equ	0400h		; max size of this overlay

	org	userdef


esc	equ	1bh
ctrlq	equ	11h
cr	equ	0dh
lf	equ	0ah
bdos	equ	5


codebgn	equ	$

;Jump table for the overlay: do NOT change this
jump_tab:
	jp	scrnpr		; screen print
	jp	mrd		; modem read with timeout
	jp	mchin		; get a character from modem
	jp	mchout		; send a character to the modem
	jp	mordy		; test for tx buffer empty
	jp	mirdy		; test for character received
	jp	sndbrk		; send break
	jp	cursadd		; cursor addressing
	jp	cls		; clear screen
	jp	invon		; inverse video on
	jp	invoff		; inverse video off
	jp	hide		; hide cursor
	jp	show		; show cursor
	jp	savecu		; save cursor position
	jp	rescu		; restore cursor position
	jp	mint		; service modem interrupt
	jp	invec		; initialise interrupt vectors
	jp	dinvec		; de-initialise interrupt vectors
	jp	mdmerr		; test uart flags for error
	jp	dtron		; turn DTR on
	jp	dtroff		; turn DTR OFF
	jp	init		; initialise uart
	jp	wait		; wait seconds
	jp	mswait		; wait milliseconds
	jp	userin		; user-defined entry routine
	jp	userout		; user-defined exit routine
	jp	getvars		; get system variables
  	JP	SETPORT		; Set port (0 or 1)

; Spare jumps for compatibility with future versions
	jp	spare		; spare for later use
	jp	spare		; spare for later use
	jp	spare		; spare for later use
	jp	spare		; spare for later use
	jp	spare		; spare for later use
	jp	spare		; spare for later use

;
; Main code starts here
;
;Screen print function
scrnpr:
				; <== Insert your own code here
	call	print
	db	1bh,'0',0                                
				; <== End of your own code
spare:
	ret

; User-defined entry routine: leave empty if not needed
userin:
        ld      bc,73ffh
        call    bdos
; map reader and punch to port1
        call    print
        db      'Version for HP12X Series',cr,lf,0
        call    print
        db      1bh,'&i0s25d4M',1bh,'&i10s16d4M',cr,lf,0
; try and set up vectors for 8 bits
        ld      bc,7effh
        ld      de,jbuf
        call    bdos
        ld      hl,(jump)
        ld      (real),hl
        ld      hl,ineight
        ld      (jump),hl
        ld      a,1
        ld      (flag),a
        ld      bc,7effh
        ld      de,jbuf
        call    bdos
	ret
; more hp stuff for 8 bit setup
ineight:call    readin
        ld      a,b
        ret
; end of more hp stuff for 8 bit setup

; User-defined exit routine: leave empty if not needed
userout:
; begin hp exit
        call    print
        db      1bh,'E',0     ; cold boot system
	ret


;Get a character from the modem: return in HL
mchin:
	push	bc
;start or HP125 code
        push    de
        ld      c,03h
        call    bdos
        pop     de

;end of HP code

	ld	l,a		; put in HL
	ld	h,0
	or	a		; set/clear Z
	pop	bc
	ret

;Send a character to the modem
mchout:
	ld	hl,2		; get the character
	add	hl,sp
	ld	a,(hl)

;start of HP code                     
        push    bc
        push    de
        ld      e,a
        ld      c,04h
        call    bdos
        pop     de
        pop     bc
;end of HP code                     
	ret			; done

;Test for output ready: return TRUE (1) in HL if ok
mordy:
;start of HP code                       

        ld      h,0
        ld      l,1

;end of hp code                      

	ld	a,l		; set/clear Z
	or	a
	ret

;Test for character at modem: return TRUE (1) in HL if so
mirdy:
;start of hp code                   

        push    bc
        push    de
        ld      bc,70ffh
        call    bdos
        ld      h,0
        ld      l,a
        pop     de
        pop     bc
        

;end og HP code                     
	ld	a,l		; set/clear Z
	or	a
	ret

;Send a break to the modem: leave empty if your system can't do it
sndbrk:
				; <== Insert your own code here

	ld	hl,300		; wait 300 mS
	call	waithm 

				; <== End of your own code
	ret
;
;Test UART flags for error: return TRUE (1) in HL if error.
mdmerr:
				; <== Insert your own code here

				; <== End of your own code
	ld	a,l		; set/clear Z
	or	a
	ret



;Turn DTR ON
dtron:
				; <== Insert your own code here

				; <== End of your own code
	ret



;Turn DTR OFF
dtroff:
				; <== Insert your own code here


				; <== End of your own code
	ret



;Initialise the uart

init:

	ld	hl,2		; get parameters
	add	hl,sp
	ex	de,hl
	call	getparm		; in HL
	ld	(brate),hl	; baud rate
	call	getparm
	ld	(parity),hl	; parity
	call	getparm
	ld	(data),hl	; data bits (BINARY 7 or 8)
	call	getparm
	ld	(stop),hl	; stop bits (BINARY 1 or 2)


				; <== Insert your own code here
				; using values below
	ld	(mspeed),a	; don't forget to load mspeed with the
				; current brate value if the new rate is
				; valid. See table of values below.
				; <== End of your own code
	ret
;--------------------------------------------------------------------------

stop:	dw	1		; stop bits
parity:	dw	'N'		; parity
data:	dw	8		; data bits
brate:	dw	7		; baud rate:

;--------------------------------------------------------------------------
;Values of brate for each baud rate
;
; baud rate    brate
;
;   110		 0
;   300		 1
;   450		 2
;   600		 3
;   710		 4
;  1200		 5
;  2400		 6
;  4800		 7
;  9600		 8
; 19200		 9
; 38400		10
; 57600         11
; 76800         12
;

;
; Set the port. ZMP supplies either 0 or 1 as a parameter.
;
setport:
	ld	hl,2		; get port number
	add	hl,sp
	ex	de,hl
	call	getparm		; in HL (values are 0 and 1)

				; <== Insert your own code here

				; <== End of your own code
	ret
;****************************************************************************
;Video terminal sequences: for the HP125                           
;Cursor addressing: 
cursadd:
	ld	hl,2		; get parameters
	add	hl,sp
	ex	de,hl
	call	getparm		; in HL
	ld	(row),hl	; row
	call	getparm
	ld	(col),hl	; column
				; <== Insert your own code here
				; using values in row and col
;start hp sequence
        call    print            
        db      esc,'&a',0
        push    bc
        push    de
        push    hl
        ld      hl,(row)
        call    conv
        ld      a,(tens)
        call    cout
        ld      a,(digits)
        call    cout
        ld      a,'r'
        call    cout
        ld      hl,(col)
        call    conv
        ld      a,(tens)
        call    cout 
        ld      a,(digits)
        call    cout
        ld      a,'C'
        call    cout
        pop     hl
        pop     de
        pop     bc
        ret
				; <== end of your own code
;more hp code for cursor control
conv:   ld      de,0000h
        ld      bc,000ah
loop16: sbc     hl,bc
        jp      m,done
        inc     e
        jp      loop16
done:   add     hl,bc
        ld      a,l
        add     a,48
        ld      (digits),a
        ld      a,e
        add     a,48
        ld      (tens),a
        ret
digits: ds      1
tens:   ds      1 
; end of hp added code for cursor control
row:	ds	2		; row
col:	ds	2		; column


;Clear screen:
cls:
	call	print
	db	1bh,'H',1bh,'J',0
	ret

;Inverse video on:
invon:
	call	print
	db	1bh,'&dA',0
	ret

;Inverse video off:
invoff:
	call	print
	db	1bh,'&d@',0
	ret

;Turn off cursor:
hide:
	ret

;Turn on cursor:
show:
	ret

;Save cursor position:
savecu:
	ret

;Restore cursor position:
rescu:
	ret

;****************************************************************************

;Service modem interrupt:
mint:
	ret			; my system doesn't need this

;Initialise interrupt vectors:
invec:
	ret			; ditto

;De-initialise interrupt vectors:
dinvec:
	ret			; ditto

;****************** End of user-defined code ********************************
;		Do not change anything below here.

;Modem character test for 100 ms
mrd:
	push	bc		; save bc
	ld	bc,100		; set limit
mrd1:
	call	mirdy		; char at modem?
	jr	nz,mrd2		; yes, exit
	ld	hl,1		; else wait 1ms
	call	waithm
	dec	bc		; loop till done
	ld	a,b
	or	c
	jr	nz,mrd1
	ld	hl,0		; none there, result=0
	xor	a
mrd2:
	pop	bc
	ret

; Inline print routine: destroys A and HL

print:
	ex	(sp),hl		; get address of string
ploop:
	ld	a,(hl)		; get next
	inc	hl		; bump pointer
	or	a		; done if zero
	jr	z,pdone
	call	cout		; else print
	jr	ploop		; and loop
pdone:
	ex	(sp),hl		; restore return address
	ret			; and quit

;
;Output a character in A to the console
;
cout:
	push	bc		; save regs
	push	de
	push	hl
	ld	e,a		; character to E
	ld	c,2
	call	bdos		; print it
	pop	hl
	pop	de
	pop	bc
	ret

;Wait(seconds)
wait:
	ld	hl,2
	add	hl,sp
	ex	de,hl		; get delay size
	call	getparm
				; fall thru to..
;Wait seconds in HL
waithls:
	push	bc		; save bc
	push	de		; de
	push	ix		; and ix
	ld	ix,0		; then point ix to 0
				; so we don't upset memory-mapped i/o

;Calculate values for loop constants. Need to have two loops to avoid
;   16-bit overflow with clock speeds above 9 MHz.

outerval	equ	(clkspd/10)+1
innerval	equ	(6667/outerval)*clkspd

wait10:
	ld	b,outerval

wait11:
	ld	de,innerval

wait12:
	bit	0,(ix)		; time-wasters
	bit	0,(ix)
	bit	0,(ix)		; 20 T-states each
	bit	0,(ix)
	bit	0,(ix)
	bit	0,(ix)
	dec	de
	ld	a,e
	ld	a,d
	or	e
	jr	nz,wait12	; 150 T-states per inner loop
	djnz	wait11		; decrement outer loop
	dec	hl		; ok, decrement count in hl
	ld	a,h
	or	l
	jr	nz,wait10
	pop	ix		; done -- restore ix
	pop	de		; de
	pop	bc		; and bc
	ret

;Wait milliseconds
mswait:
	ld	hl,2
	add	hl,sp
	ex	de,hl		; get delay size
	call	getparm
				; fall thru to..
;Wait milliseconds in HL
waithm:
	push	de
w1ms0:
	ld	de,39*clkspd
w1ms1:
	dec	de
	ld	a,d
	or	e
	jr	nz,w1ms1
	dec	hl
	ld	a,h
	or	l
	jr	nz,w1ms0
	pop	de
	ret

;Get next parameter from (de) into hl
getparm:
	ex	de,hl		; get address into hl
	ld	e,(hl)		; get lo
	inc	hl
	ld	d,(hl)		; then hi
	inc	hl		; bump for next
	ex	de,hl		; result in hl, address still in de
	ret

;Get address of user-defined variables

getvars:
	ld	hl,uservars
	ret

uservars:
	dw	overdrive	; .OVR etc. drive/user
	dw	overuser
;add hp stuff
readin: db      0c3h
real:   ds      2
jvn:    db      7
flag:   db      0
opcode: ds      1
jump:   ds      2
jbuf:   equ     jvn
;end added hp stuff

	end
                                                  
